/*
 * ResManager.h
 *
 *  Created on: 24 oct. 2010
 *      Author: seeme
 *      Ce manager est unique (singleton).
 *      Il précharge les ressources, et ne les charges qu'une fois si on en a besoin.
 *      Il faut penser à décrémenter le compteur de référence pour qu'il puisse les supprimer.
 *      Il se charge de tout nettoyer si on le détruit.
 */

#ifndef RESMANAGER_H_
#define RESMANAGER_H_

#include <ctime>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include "Resources/Resource.h"
#include "Resources/ResourceFactory.h"
#include "../Tools/Misc/Singleton.h"

//Si on change le type de Handle
#define IS_VALID_HANDLE(_rh) ((_rh == "") ? true: false)
#define IS_INVALID_HANDLE(_rh) ((_rh == "") ? false: true)


typedef std::string HANDLE;
typedef std::map<HANDLE, Resource*> ResMap;
typedef ResMap::iterator ResMapItor;
typedef ResMap::value_type ResMapPair;

class ResCache: public Singleton<ResCache>{

   //Singleton features
   friend class Singleton<ResCache>;

public:
	ResCache();
	virtual ~ResCache(){ destroy(); }

	//Initialise le tout
	bool create(unsigned int size);
	//Détruit toutes les resources
	void destroy();

	//Permet de bloquer de la mémoire, même si on n'alloue rien
	bool reserveMemory(size_t size);

	//La mémoire max autorisée, à dégager.
	bool setMaximumMemory(size_t nMem);

	//On supprime complètement la ressource (y compris sa
	//version "déchargée"
	bool destroyResource(Resource* pResource);
	bool destroyResource(HANDLE rhUniqueID);

	//On garde la version déchargée pour des appels ultérieurs,
	//Mais le gros des données est flushed, sa taille sera zero.
	void releaseResource(HANDLE uniHandle);

	//On récupère un pointeur sur une ressource.
	//On ne peut pas delete ce pointeur.
	//On doit décrémenter le compteur de références pour qu'il soit
	//Delete (sauf si on kill le manager)
	Resource* getResource(HANDLE uniqHandle);

	//Inutilisé pour le moment,
	//Permet de spécifier l'emplacement par défaut des packages de ressources
	void setPackageDir(const char* dir);
	std::string getPackageDir(){return m_packageDir;}

	//Parser un fichier de ressources
	void loadPackage(const char* dir);

	//Faire le ménage
	void clear();

	//Ajouter une ressource qui ne vient pas du package (diamants)
	void addResource(HANDLE, Resource*);

protected:
	//On utilise plus de mémoire (au chargement d'une ressource)
	inline void addMemory(unsigned int size){m_currentUsedMemory += size;}

	//On libère de la mémoire (déchargement d'une ressource)
	inline void removeMemory(unsigned int size){m_currentUsedMemory -= size;}

	//Très importante, va déterminer s'il faut virer des ressources,
	//Et si oui, lesquelles.
	bool checkForOverallocation();

	std::vector<std::string> split(const std::string source, const char separator);

protected:
	HANDLE m_nextResourceHandle;
	unsigned int m_currentUsedMemory;
	unsigned int m_maximumMemory;
	ResMap m_resourceMap;
	std::string m_packageDir;
	ResourceFactory m_resFactory;
};

#endif /* RESMANAGER_H_ */
